<?php
/**
 * @author  sandeep
 */

require_once 'Zend/Mail/Storage/Imap.php';
 
class Core_Mail_Imap_Client
{
    private static $_storage;
    
    private static $_transport;
    
    private $_mailParser;
    
    /**
     * Creates a connection to Imap server with supplied credentials
     * @param $hostname
     * @param $port
     * @param $ssl
     * @param $username
     * @param $password
     * @return unknown_type
     */
    public function connect($hostname, $port, $ssl, $username, $password, $folder = 'INBOX')
    {
        try {
         self::$_storage = new Zend_Mail_Storage_Imap(array('host'     => $hostname,
                                                     	    'user'     => $username,
                                                            'password' => $password,
                                                            'ssl'	   => $ssl,
                                                            'port'	   => $port,
                                                            'folder'   => $folder
                                                                        ));
         require_once 'MailParser.php';
         $this->_mailParser = new MailParser();
         $this->checkFolders();
         $this->selectFolder('INBOX');
        } catch (Exception $e) {
             throw $e;   
        }
    }
    
    /**
     * Check for default folders 
     * if folders are not there create it.
     * 
     * @return unknown_type
     */
    public function checkFolders()
    {
        if (!$this->hasFolder('Trash')) {
            $this->getStorage()->createFolder('Trash');
        }
        if (!$this->hasFolder('Sent')) {
            $this->getStorage()->createFolder('Sent');
        }
    }
    
	/**
     * Returns an instance of this object.
     *
     * @param string $username
     * @param string $password
     * @param Zend_Config $settings
     * @return MailAgent
     */
    /* */
    
    public function getAllFolders()
    {
        $folderIterator = new RecursiveIteratorIterator(self::$_storage->getFolders(),
                                                     RecursiveIteratorIterator::SELF_FIRST);
        
        $folders= array();
        $i = 0;
        foreach ($folderIterator as $localName => $folder) {
            $folders[$i] = array();
            $folders[$i]['localName']  = $folder->getLocalName();
            $folders[$i]['globalName'] = $folder->getGlobalName();
            $folders[$i]['selectable'] = $folder->isSelectable();
            $i++;
        }                                                         
        return $folders;
    }
    
    public function selectFolder($folderName)
    {
        if ($this->_isValidFolder($folderName)) {
            self::$_storage->selectFolder($folderName);
        } else {
            throw new Exception('Folder not found please check the name and try again');
        }
    }
    
    private function _isValidFolder($folderName)
    {
        $found = 0;
        $folders = $this->getAllFolders();
        foreach ($folders as $folder) {
            if ($folderName == $folder['localName'] || $folderName == $folder['globalName']) {
                $found++;
            }
        }
        return $found;
    }
    
    public function getAllMessages()
    {
        $messages = array();
        $messageCount = 1;
        foreach (self::$_storage as $message) {
            $messages[$messageCount] = array();
            $uid = self::$_storage->getUniqueId($messageCount);
            $messages[$messageCount] = $this->_mailParser->parseMail($message, $uid);
            $messageCount++;
        }
        return $messages;
    }
    
    public function getMessage($uid)
    {
        $messageObject = self::$_storage->getMessage(self::$_storage->getNumberByUniqueId($uid));
        return $this->_mailParser->parseMail($messageObject, $uid);
    }
    
    public function getMessages($start, $end)
    {
        $messages = array();
        for ($messageCount = $start; $messageCount < $end; $messageCount++) {
            $message = self::$_storage->getMessage($messageCount);
            $uid = self::$_storage->getUniqueId($messageCount);
            $messages[$messageCount] = $this->_mailParser->parseMail($message, $uid);
        }
        return $messages;
    }
    
    public function getAttachment($uid, $attachmentId)
    {
        $message = $this->getMessage($uid);
        $this->_mailParser->getAttachment($message, $attachmentId);
    }
    
    public function getMailCount()
    {
         return self::$_storage->countMessages();   
    }
    
    public function sendMessage($to, $cc, $subject, $attachment, $body)
    {
        $auth = Zend_Auth::getInstance();
        $identity = $auth->getIdentity();
        $password = $identity->details['user_password'];
        $userEmail = $identity->details['user_name'];
        $username = explode('@', $userEmail);
        $username = $username[0];
        
        require_once 'Zend/Mail.php';
        $mail = new Zend_Mail();
        $mail->addTo($to);
        $mail->addCc($cc);
        $mail->setFrom($userEmail, $username);
        $mail->setSubject($subject);
        
        if(count($attachment['name']) > 0) {
            for ($i = 0; $i < count($attachment['name']); $i++) {
                $mail->createAttachment(file_get_contents($attachment['tmp_name'][$i]),
                                    $attachment['type'][$i],
                                    Zend_Mime::DISPOSITION_ATTACHMENT,
                                    Zend_Mime::ENCODING_BASE64,
                                    $attachment['name'][$i]);
            }
        }
        
        $mail->setBodyHtml($body);
        if($mail->send()) {
            $this->saveInSent($to, $cc, $subject, $attachment, $body);
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * Save the sent mail to Sent folder.
     * 
     * @param $to string 
     * @param $cc string 
     * @param $subject string
     * @param $attachment array
     * @param $body string 
     * @return void
     */
    public function saveInSent($to, $cc, $subject, $attachment, $body)
    {
        $auth = Zend_Auth::getInstance();
        $identity = $auth->getIdentity();
        $userEmail = $identity->details['user_name'];
        $firstname = $identity->details['first_name'];
        $lastname  = $identity->details['last_name'];
        $from = $firstname .' ' .$lastname .' ' . '<' . $userEmail . '>';

        $headers = '';
        $headers .= "From: " . $from ."\r\n";
        $headers .= "To: " . $to. "\r\n";
        $headers .= "Cc: " . $cc. "\r\n";
        $headers .= "Date:". date('r')."\r\n";
        $headers .= "Subject: " .$subject. "\r\n";
        $headers .= "Content-type:text/plain; charset=iso-8859-1\r\n";
        $headers .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
        $headers .= $body;
        
        /**
         * save the attachment(s) to sent folder.
         */
        /*if(count($attachment['name']) > 0) {
            for ($i = 0; $i < count($attachment['name']); $i++) {
                $fileContent = file_get_contents($attachment['tmp_name'][$i]);
                $fileContent = chunk_split(base64_encode($fileContent));
                $header = $this->creatAttachmentHeader();
                $headers .= $header[0];
                $data = array('name'=>$attachment['name'][$i], 'file'=>$fileContent, 'message'=>$body,'uid' => $header[1]);
                $headers .= $this->createAttachmentBody($data);
               }
       }*/
        $this->getStorage()->appendMessage($headers,'Sent');
    }
    
    /**
     * Create Attachments.
     * 
     * @param array $attachment
     * @param unknown_type $message
     * @return string
     */
    public function creatAttachmentHeader()
    {
        $uid      = md5(uniqid(time()));
        $headers  = "MIME-Version: 1.0\r\n";
        $headers .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
        $headers .= "--".$uid."\r\n";
        return array($headers,$uid);
    }
    
    
    /**
     * Get the Body Content.
     * 
     * @param array $data
     * @return string
     */
    public function createAttachmentBody(array $data)
    {
        $fileName = str_replace('"', '', $data['name']);
        $headers = "--".$data['uid']."\r\n";
        $headers .= "Content-Type: application/octet-stream; name=\"" . $fileName . "\"\r\n";
        $headers .= "Content-Transfer-Encoding: base64\r\n";
        $headers .= "Content-Disposition: attachment; filename=\"" . $fileName . "\"\r\n\r\n";
        $headers .= $data['file'] . '\r\n\r\n';
        $headers .= "--".$data['uid']."--\r\n";
        return $headers;
    }
    
    
    public function connectSMTP($server, $username, $password)
    {
        $config = array('auth' => 'login',
                'username' => $username,
                'password' => $password,
                'port'     => 465,
                'ssl'      => 'SSL'
                );
        
        require_once 'Zend/Mail/Transport/Smtp.php';
        self::$_transport = new Zend_Mail_Transport_Smtp($server, $config);
    }
    
    public function deleteMessage($uid)
    {
        if ('Trash' == $this->getStorage()->getCurrentFolder()) {
            return $this->getStorage()->removeMessage(self::$_storage->getNumberByUniqueId($uid));    
        } else {
            return $this->getStorage()->moveMessage(self::$_storage->getNumberByUniqueId($uid),'Trash');
        }
        
        
    }
    
    private function _validateMail($mail)
    {}
    
    private function _createMessage()
    {}
    
    /*public function getMessage($uid)
    {
        $messageObject = self::$_storage->getMessage(self::$_storage->getNumberByUniqueId($uid));
        Zend_Debug::dump($messageObject->getContent());die;
    }*/
    
    public function hasFolder($folderName)
    {
        $currentFolder = $this->getStorage()->getCurrentFolder();
        try {
            $this->getStorage()->selectFolder($folderName);
        } catch (Exception $e) {
            return false;
        } 
        $this->selectFolder($currentFolder);
        return true;
        
    }
    
    public function getStorage()
    {
        return self::$_storage;
    }
}